package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatsResult;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {

    @Autowired
    private StrategyTemplateRepository repository;

    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    public Page<StrategyTemplate> query(SearchQueryObject qo) {
        Page<StrategyTemplate> page = null;
        switch (qo.getType()){
            case SearchQueryObject.CONDITION_UNABROAD:
                //查询国内
                page = repository.findByProvinceId(qo.getTypeValue(),qo.getPageable());
                break;
            case SearchQueryObject.CONDITION_ABROAD:
                //查询国外
                page = repository.findByCountryId(qo.getTypeValue(),qo.getPageable());
                break;
            case SearchQueryObject.CONDITION_THEME:
                //查询主题
                page = repository.findByThemeId(qo.getTypeValue(),qo.getPageable());
                break;
            default:
                page = repository.findAll(qo.getPageable());
        }
        return page;
    }

    public List<StatsResult> listCondition(int condition) {
        String id = null;
        String name = null;
        switch (condition){
            case SearchQueryObject.CONDITION_UNABROAD:
                id = "provinceId";
                name = "provinceName";break;
            case SearchQueryObject.CONDITION_ABROAD:
                id = "countryId";
                name = "countryName";break;
            case SearchQueryObject.CONDITION_THEME:
                id = "themeId";
                name = "themeName";break;
        }
        return groupSearch(id, name);
    }
    /*
    "aggs": {
        "condition": {
          "composite": {
            "sources": [
              {
                "id": {
                  "terms": {
                    "field": "provinceId"
                  }
                }
              }, {
                "name": {
                  "terms": {
                    "field": "provinceName"
                  }
                }
              }
            ]
          }
        }
      }
     */
    private List<StatsResult> groupSearch(String... vals) {
        String condition = "condition";
        String id = "id";
        String name = "name";
        List<StatsResult> list = new ArrayList<>();

        //统一封装查询条件
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withPageable(PageRequest.of(0,1));

        //每个分桶字段
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        sources.add(new TermsValuesSourceBuilder(id).field(vals[0]));
        sources.add(new TermsValuesSourceBuilder(name).field(vals[1]));

        //多字段统一起来
        CompositeAggregationBuilder aggs = new CompositeAggregationBuilder(condition,sources);

        //分组查询
        builder.addAggregation(aggs);

        //如果查询的是国内
        if (vals[0].equals("provinceId")) {
            builder.withQuery(QueryBuilders.termQuery("countryId","1"));
        }

        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        InternalComposite agg = (InternalComposite) page.getAggregation(condition);

        for (CompositeAggregation.Bucket bucket : agg.getBuckets()) {
            Map<String, Object> key = bucket.getKey();
            Object idX = key.get(id);
            Object nameX = key.get(name);
            long count = bucket.getDocCount();
            StatsResult result = new StatsResult(Long.parseLong(idX.toString()), nameX.toString(), count);
            list.add(result);
        }
        return list;
    }

    public List<Map<String, Object>> listThemeCommendTop10() {
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        List<StatsResult> vos = groupSearch("themeId", "themeName");

        //排序, 按照攻略数量排
        Collections.sort(vos, (o1,o2) ->{
            Long val = o1.getCount() - o2.getCount();
            return val.intValue();
        });

        //截取攻略数量前十个, 包前不包后
        if(vos.size() > 10) {
            vos.subList(0, 10);
        }

        for (StatsResult vo : vos) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("theme",vo); //显示左栏主题名称

            //为了避免查询出来相同的目的地在页面上显示, 用set, 它具有排重功能
            //set排重依靠的是hashcode和equals方法, StatsResult类里面已经复写了
            HashSet<StatsResult> set = new HashSet<>();
            //根据主题id查询攻略
            List<StrategyTemplate> strategyTemplates =
                    repository.findByThemeId(vo.getId(), null).getContent();
            for (StrategyTemplate template : strategyTemplates) {
                StatsResult result = new StatsResult();
                result.setId(template.getDestId());
                result.setName(template.getDestName());
                set.add(result);
            }
            map.put("dests",set);
            list.add(map);
        }
        return list;
    }

    public List<StrategyTemplate> listByDestName(String keyword) {
        return repository.findByDestName(keyword);
    }
}
